package com.kehutong.common.tencent;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

public class Library {

	private static final String OS_NAME = get("os.name");
	
	public static boolean isWindows() {
		if (OS_NAME == null) {
			return false;
		}
		
		return OS_NAME.startsWith("Windows");
	}
	
	public static boolean isLinux() {
		if (OS_NAME == null) {
			return false;
		}
		
		return OS_NAME.startsWith("Linux") || OS_NAME.startsWith("LINUX");
	}

	public static void setLibrarys() {
		final List<File> writeFile = new ArrayList<>();

		final List<String> files = getLibrarys();
		for (String f : files) {
			if (isLinux()) {
				writeFile.add(setLibrary("/libs/linux/", f));
			} else {
				writeFile.add(setLibrary("/libs/win/", f));
			}
		}

		deleteOnExit(writeFile);
	}
	

	private static File setLibrary(String pathName, String fileName) {
		try {
			String libpath = System.getProperty("java.library.path");
			if (libpath == null || libpath.length() == 0) {
				throw new RuntimeException("java.library.path is null");
			}

			String path = null;
			StringTokenizer st = new StringTokenizer(libpath, System.getProperty("path.separator"));
			while (st.hasMoreElements()) {
				path = st.nextToken();
				if (path.equals(".")) {
					break;
				}
			}
			
			if (path == null || path.length() == 0) {
				throw new RuntimeException("can not split library path:" + libpath);
			}

			final File dllFile = new File(new File(path), fileName);
			if (dllFile.exists()) {
				return dllFile;
			}

			try (InputStream inputStream = readFile(pathName, fileName);
				 FileOutputStream outputStream = new FileOutputStream(dllFile)) {
				byte[] array = new byte[8192];
				int bytesRead = -1;
				while ((bytesRead = inputStream.read(array)) != -1) {
					outputStream.write(array, 0, bytesRead);
				}
				outputStream.flush();
			}

			return dllFile;
		} catch (Throwable e) {
			e.printStackTrace();
			throw new RuntimeException("load .dll error!", e);
		}
	}

	private static void deleteOnExit(List<File> files) {
		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				try {
					Thread.sleep(5000L);
					for (File f : files) {
						f.deleteOnExit();
					}
				} catch (InterruptedException e) {
				}
			}
		});
	}
	
    private static InputStream readFile(String path, String fileName)
    {
    	try {
    		return Library.class.getResourceAsStream(path + fileName);
    	} catch (Exception e) {
    		try {
				return Library.class.getClassLoader().getResourceAsStream(path + fileName);
			} catch (Exception e1) {
				e.printStackTrace();
				throw e1;
			}
		}
    }
    
    private static List<String> getLibrarys() {
    	if (isWindows()) {
			return Arrays.asList("WeWorkFinanceSdk.dll", "libcurl.dll", "libeay32.dll", "libprotobuf.dll", "ssleay32.dll");
		} else if (isLinux()) {
			return Arrays.asList("WeWorkFinanceSdk.so");
		} else {
			throw new RuntimeException("unsupport os type:" + OS_NAME);
		}
    }

	static String get(final String name) {
		String value = null;
		try {
			if (System.getSecurityManager() == null) {
				value = System.getProperty(name);
			} else {
				value = AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty(name));
			}
		} catch (Exception ignore) {
		}

		return value;
	}
}
